<?php

/**
 * JingYao-backend
 *
 * @link     https://gitee.com/wang-zhihui-release/jingyao-backend
 * @apiDocument https://gitee.com/wang-zhihui-release/jingyao-backend/wikis/
 */

namespace App\Services;

use App\Enums\AreaEnum;
use App\Enums\CheckStatusEnum;
use App\Enums\EducationEnum;
use App\Enums\IsVaccinationEnum;
use App\Enums\UserIdentityEnum;
use App\Enums\UserSexEnum;
use App\Models\CensusUserNativePlace;
use App\Models\Enum;
use App\Models\PassCard;
use App\Models\UserCountDaily;
use App\Models\UserProfile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class DataChartService
{
    public function getUserProfileCount()
    {
        return UserProfile::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->count();
    }

    public function getFlowUserCount()
    {
        return UserProfile::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->where('identity', UserIdentityEnum::FLOW_USER)->count();
    }

    public function getNotFlowUserCount()
    {
        return UserProfile::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->whereIn('identity', [
                UserIdentityEnum::HOUSER,
                UserIdentityEnum::NORMAL,
            ])->count();
    }

    public function getDayFlowUserDiff()
    {
        return [
            'todayFlowUserCount' => $this->getTodayFlowUsers(),
            'yesterdayFlowUserCount' => $this->getYesterdayFlowUserCount(),
        ];
    }

    public function getWorkRate()
    {
        $allUser = UserProfile::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->count();
        $workUser = UserProfile::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->whereNotNull('company_name')->count();
        return [
            'all_user' => $allUser,
            'work_user' => $workUser,
        ];
    }

    public function getProvince()
    {
        return CensusUserNativePlace::query()->get();
    }

    public function getSexs()
    {
        $manNumber = UserProfile::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->where('sex', UserSexEnum::MAN)->count();
        $womanNumber = UserProfile::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->where('sex', UserSexEnum::WOMAN)->count();
        return [
            'man_number' => $manNumber,
            'woman_number' => $womanNumber,
        ];
    }

    public function identifies()
    {
        $flowUserNumer = UserProfile::query()->where('identity', UserIdentityEnum::FLOW_USER)
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->count();

        $houserNumber = UserProfile::query()->where('identity', UserIdentityEnum::HOUSER)
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->count();

        $normalNumber = UserProfile::query()->where('identity', UserIdentityEnum::NORMAL)
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->count();

        return [
            'flow_user_count' => $flowUserNumer,
            'houser_count' => $houserNumber,
            'normal_count' => $normalNumber,
        ];
    }

    public function industries()
    {
        $industries = Enum::query()->where('type', 1)->get()->toArray();

        $user = UserProfile::query()->select('industry', DB::raw('count(*) as number'))
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->doesntHave('check')
            ->groupBy('industry')->get()->toArray();

        $result = [];
        $map = array_column($user, null, 'industry');
        foreach ($industries as $id => $industry) {
            array_push($result, [
                'industry' => $industry['title'],
                'number' => isset($map[$id]) ? $map[$id]['number'] : 0,
            ]);
        }

        return $result;
    }

    public function ages()
    {
        $res = Redis::get(config('census.user_age_key'));
        return json_decode($res);
    }

    public function areas()
    {
        $res = Redis::get(config('census.user_area_key'));
        $areas = AreaEnum::toArray();
        $redisResult = json_decode($res, true);
        $redisResultMap = array_column($redisResult, null, 'area');
        $result = [];
        foreach ($areas as $key => $area) {
            array_push($result, [
                'area' => $key,
                'area_name' => $area,
                'number' => isset($redisResultMap[$key]) ? $redisResultMap[$key]['number'] : 0,
            ]);
        }
        return $result;
    }

    public function getEducation()
    {
        $result = [];

        $educations = EducationEnum::toArray();

        foreach ($educations as $id => $education) {
            array_push($result, [
                'id' => $id,
                'name' => $education,
            ]);
        }

        $res = UserProfile::query()->select('education', DB::raw('count(*) as number'))
            ->doesntHave('check')
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->groupBy('education')->get()->toArray();

        $groupMap = array_column($res, null, 'education');
        foreach ($result as &$value) {
            isset($groupMap[$value['id']])
                ? $value['number'] = $groupMap[$value['id']]['number']
                : $value['number'] = 0;
        }
        return $result;
    }

    public function getMonthUserCount()
    {
//        $year = date('Y', time());
//        $monthDate = [
//            '01-01', '02-01', '03-01', '04-01',
//            '05-01', '06-01', '07-01', '08-01',
//            '09-01', '10-01', '11-01', '12-01',
//        ];
//
//        foreach ($monthDate as &$date) {
//            $date = sprintf('%s-%s', $year, $date);
//        }

        $monthDate = [];

        for ($i = 0; $i < 12; ++$i) {
            $monthDate[$i] = date('Y-m', strtotime(date('Y-m-01') . '-' . $i . 'month')) . '-01';
        }
        $monthDate = array_reverse($monthDate);
        /*
        $res = UserCountDaily::query()->whereIn('date', $monthDate)->get()->toArray();


        $map = [];
        if (! empty($res)) {
            $map = array_column($res, null, 'date');
        }
        */
        $result = [];

        foreach ($monthDate as $monthFirst) {
            $userCounts = UserCountDaily::query()
                ->where('date', 'like', substr($monthFirst, 0, 7) . '%')
                ->orderByDesc('id')
                ->first();

            $flowUserCount = $userCounts->flow_user_count ?? 0;
            $houserUserCount = $userCounts->houser_count ?? 0;
            $normalUserCount = $userCounts->normal_count ?? 0;
            array_push($result, [
                'month' => substr($monthFirst, 0, 7),
                'flow_user_count' => $flowUserCount,
                'houser_count' => $houserUserCount,
                'normal_count' => $houserUserCount + $normalUserCount,
            ]);
        }

        return $result;
    }

    public function companies()
    {
        $areas = [
            [
                'area' => AreaEnum::COMPANY_ONE,
                'name' => AreaEnum::__COMPANY_ONE,
            ],
            [
                'area' => AreaEnum::COMPANY_TWO,
                'name' => AreaEnum::__COMPANY_TWO,
            ],
            [
                'area' => AreaEnum::COMPANY_THREE,
                'name' => AreaEnum::__COMPANY_THREE,
            ],
        ];
        $res = Redis::get(config('census.user_area_key'));
        $redisResult = json_decode($res, true);
        $redisResultMap = array_column($redisResult, null, 'area');
        $result = [];
        foreach ($areas as $key => $area) {
            array_push($result, [
                'area' => $area['area'],
                'name' => $area['name'],
                'number' => isset($redisResultMap[$area['area']]) ? $redisResultMap[$area['area']]['number'] : 0,
            ]);
        }
        return $result;
    }

    public function vaccinations()
    {
        $all = UserProfile::query()
            ->doesntHave('check')
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)->count();

        $vaccinations = UserProfile::query()
            ->doesntHave('check')
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->where('is_vaccination', IsVaccinationEnum::YES)->count();

        return [
            'all' => $all,
            'vaccinations' => $vaccinations,
        ];
    }

    public function getPassCard()
    {
        return PassCard::query()
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->count();
    }

    private function getYesterdayFlowUserCount(): int
    {
        /** @var null|UserCountDaily $yesterdayUserCount */
        $yesterdayUserCount = UserCountDaily::query()
            ->where('date', date('Y-m-d', strtotime('-1 day')))
            ->first();
        if (empty($yesterdayUserCount)) {
            return 0;
        }
        return $yesterdayUserCount->flow_user_count;
    }

    private function getTodayFlowUsers(): int
    {
        /** @var null|UserCountDaily $todayUserCount */
        $todayUserCount = UserCountDaily::query()->where('date', date('Y-m-d', time()))->first();
        if (empty($todayUserCount)) {
            return 0;
        }
        return $todayUserCount->flow_user_count;
    }
}
